﻿using UnityEngine;
using UnityEngine.UI;
using UnityEngine.Sprites;
using System;

namespace Mars.MeshUI
{
    public class MeshImg : CustomUIGraphic
    {
        public enum MirrorType
        {
            Horizontal,
            Vertical,
            Quarter,
        }

        public Image.Type type = default;

        public Sprite activeSprite
        {
            get { return m_Sprite; }

            set
            {
                if (value == null)
                {
                    return;
                }

                m_Sprite = value;
            }
        }

        public bool ableSlid
        {
            get
            {
                if (vertices == null)
                {
                    return false;
                }

                return vertices.Length == 4 || vertices.Length == 16;
            }
        }

        [SerializeField] private Sprite m_Sprite = default;

        [NonSerialized] public Vector4 alphaRect;

        private Vector4 ltrb = Vector4.zero;

        [NonSerialized] public Vector4 spriteUVPara;

        public float pixelsPerUnit
        {
            get
            {
                if (activeSprite)
                    return activeSprite.pixelsPerUnit;
                else
                    return 100;
            }
        }

        [SerializeField] private Color m_Color = Color.white;

        public Color color
        {
            get { return m_Color; }

            set
            {
                if (m_Color == value)
                    return;

                m_Color = value;
                colorDrity = true;
            }
        }

        public float fillAmount
        {
            get { return m_FillAmount; }

            set
            {
                if (type == Image.Type.Sliced)
                    return;

                if (value == m_FillAmount)
                {
                    return;
                }

                m_OldFillAmount = m_FillAmount;
                m_FillAmount = Mathf.Clamp01(value);

                fillDrity = true;
            }
        }

        [SerializeField] private float m_FillAmount = 1;
        private float m_OldFillAmount;

        public bool hasBorder
        {
            get
            {
                if (activeSprite != null)
                {
                    Vector4 v = activeSprite.border;
                    return v.sqrMagnitude > 0f;
                }

                return false;
            }
        }

        private bool fillDrity;
        private bool colorDrity;
        private bool spriteDirty;

        static readonly Vector4[] s_Uv = new Vector4[4];
        static readonly Vector2[] s_Xy = new Vector2[4];

        public override bool Init(MeshCanvas _canvas)
        {
            canvas = _canvas;

            if (canvas == null)
            {
                return false;
            }

            if (m_Sprite != null && activeSprite != null)
            {
                var rect = activeSprite.textureRect;
                spriteUVPara = new Vector4(rect.x / activeSprite.texture.width, rect.y / activeSprite.texture.height,
                    rect.width / activeSprite.texture.width, rect.height / activeSprite.texture.height);


                GenerateSprite();

                if (canvas.mainTexture == null)
                {
                    canvas.mainTexture = m_Sprite.texture;
                }


                if (vertices.Length == 6)
                {
                    IndicType = mirrorType == MirrorType.Horizontal
                        ? VertexHelperEx.VertexIndicType.VertexQuad6H
                        : VertexHelperEx.VertexIndicType.VertexQuad6V;
                }
            }


            if (gameObject != null)
            {
                SetVisable(true);
            }

            return true;
        }

        public override void SetVisable(bool enable)
        {
            base.SetVisable(enable);
        }

        public override void SetPosition(Vector3 localPosition)
        {
            base.SetPosition(localPosition);
        }

        public void ComputerUVRect()
        {
            var uv = DataUtility.GetOuterUV(activeSprite);
            spriteUVPara = new Vector4(uv.x, uv.y, uv.z - uv.x, uv.w - uv.y);
        }

        public void SetSprite(Sprite sp)
        {
            if (sp == null)
                return;

            if (sp == activeSprite)
                return;

            activeSprite = sp;

            ComputerUVRect();

            spriteDirty = true;
            GenerateSprite();
        }

        void SetColor(Color32 color)
        {
            if (vertices == null)
                return;

            for (int i = 0; i < vertices.Length; i++)
            {
                vertices[i].color = color;
            }

            SetCanvasFlagDirty(MeshCanvasDirtyFlag.kColor);
        }

        void SetColor()
        {
            if (vertices == null)
                return;

            if (canvas == null)
                return;

            if (canvas.useVertexColor == false)
                return;

            for (int i = 0; i < vertices.Length; i++)
            {
                vertices[i].color = color;
            }

            SetCanvasFlagDirty(MeshCanvasDirtyFlag.kColor);
        }

        void SetAlpha(byte alpha)
        {
            if (canvas == null)
                return;

            if (vertices == null)
                return;

            if (canvas.useVertexColor == false)
                return;

            for (int i = 0; i < vertices.Length; i++)
            {
                vertices[i].color.a = alpha;
            }

            SetCanvasFlagDirty(MeshCanvasDirtyFlag.kColor);
        }

        public void SetFillAmount(float toFill)
        {
            if (toFill < 0.001)
            {
                vertices[2].position.x = vertices[1].position.x;
                vertices[3].position.x = vertices[1].position.x;
            }
            else
            {
                var uv = DataUtility.GetOuterUV(m_Sprite);

                float fill = (uv.z - uv.x) * m_FillAmount; //rgb fill
                float fillAlpha = (alphaRect.z - alphaRect.x) * m_FillAmount; //alpha fill

                vertices[2].position.x = vertices[1].position.x + size.x * m_FillAmount;
                vertices[3].position.x = vertices[2].position.x;

                vertices[2].uv.x = vertices[1].uv.x + fill;
                vertices[3].uv.x = vertices[2].uv.x;

                vertices[2].uv.z = vertices[1].uv.z + fillAlpha;
                vertices[3].uv.z = vertices[2].uv.z;
            }

            if (isVisible)
            {
                SetCanvasFlagDirty(MeshCanvasDirtyFlag.kPosition | MeshCanvasDirtyFlag.kUv);
            }
        }

        public void SetFillAmountRadial360(float toFill, bool upload)
        {
            if (vertices.Length != 16)
            {
                return;
            }

            if (toFill < 0.001)
            {
                if (isVisible == false)
                {
                    return;
                }

                for (int i = 0; i < vertices.Length; i++)
                {
                    vertices[i].position = Vector3.zero;
                }

                SetCanvasFlagDirty(MeshCanvasDirtyFlag.kPosition);
                return;
            }

            Vector4 outer = activeSprite != null ? DataUtility.GetOuterUV(activeSprite) : Vector4.zero;

            float tx0 = outer.x;
            float ty0 = outer.y;
            float tx1 = outer.z;
            float ty1 = outer.w;

            for (int corner = 0; corner < 4; ++corner)
            {
                float fx0, fx1, fy0, fy1;

                if (corner < 2)
                {
                    fx0 = 0f;
                    fx1 = 0.5f;
                }
                else
                {
                    fx0 = 0.5f;
                    fx1 = 1f;
                }

                if (corner == 0 || corner == 3)
                {
                    fy0 = 0f;
                    fy1 = 0.5f;
                }
                else
                {
                    fy0 = 0.5f;
                    fy1 = 1f;
                }

                s_Xy[0].x = Mathf.Lerp(rect.x, rect.z, fx0);
                s_Xy[1].x = s_Xy[0].x;
                s_Xy[2].x = Mathf.Lerp(rect.x, rect.z, fx1);
                s_Xy[3].x = s_Xy[2].x;

                s_Xy[0].y = Mathf.Lerp(rect.y, rect.w, fy0);
                s_Xy[1].y = Mathf.Lerp(rect.y, rect.w, fy1);
                s_Xy[2].y = s_Xy[1].y;
                s_Xy[3].y = s_Xy[0].y;

                s_Uv[0].x = Mathf.Lerp(tx0, tx1, fx0);
                s_Uv[1].x = s_Uv[0].x;
                s_Uv[2].x = Mathf.Lerp(tx0, tx1, fx1);
                s_Uv[3].x = s_Uv[2].x;

                s_Uv[0].y = Mathf.Lerp(ty0, ty1, fy0);
                s_Uv[1].y = Mathf.Lerp(ty0, ty1, fy1);
                s_Uv[2].y = s_Uv[1].y;
                s_Uv[3].y = s_Uv[0].y;

                s_Uv[0].z = Mathf.Lerp(alphaRect.x, alphaRect.z, fx0);
                s_Uv[1].z = s_Uv[0].z;
                s_Uv[2].z = Mathf.Lerp(alphaRect.x, alphaRect.z, fx1);
                s_Uv[3].z = s_Uv[2].z;

                s_Uv[0].w = Mathf.Lerp(alphaRect.y, alphaRect.w, fy0);
                s_Uv[1].w = Mathf.Lerp(alphaRect.y, alphaRect.w, fy1);
                s_Uv[2].w = s_Uv[1].w;
                s_Uv[3].w = s_Uv[0].w;

                float val = m_FillAmount * 4f - ((corner + 2) % 4);

                int quadCount = corner * 4;

                if (m_FillAmount == 1 || RadialCut(s_Xy, s_Uv, Mathf.Clamp01(val), true, ((corner + 2) % 4)))
                {
                    vertices[quadCount].position = s_Xy[0];
                    vertices[quadCount + 1].position = s_Xy[1];
                    vertices[quadCount + 2].position = s_Xy[2];
                    vertices[quadCount + 3].position = s_Xy[3];

                    vertices[quadCount].uv = s_Uv[0];
                    vertices[quadCount + 1].uv = s_Uv[1];
                    vertices[quadCount + 2].uv = s_Uv[2];
                    vertices[quadCount + 3].uv = s_Uv[3];
                }
                else
                {
                    vertices[quadCount].position = Vector3.zero;
                    vertices[quadCount + 1].position = Vector3.zero;
                    vertices[quadCount + 2].position = Vector3.zero;
                    vertices[quadCount + 3].position = Vector3.zero;
                }
            }

            if (isVisible && upload)
            {
                SetCanvasFlagDirty(MeshCanvasDirtyFlag.kPosition | MeshCanvasDirtyFlag.kUv);
            }
        }

        public void AddRadial360(Mesh mesh)
        {
            if (mesh.vertexCount < 4)
                return;

            vertices = new VertexData[16];

            SetFillAmountRadial360(1, false);

            SetColor(mesh.colors32[0]);
        }

        public override bool Rebuild()
        {
            if (isVisible == false)
            {
                return false;
            }

            if (canvas == null)
            {
                return false;
            }

            if (sizeDrity)
            {
                GenerateSize();
                deltaSize = Vector2.zero;
                sizeDrity = false;
            }

            if (colorDrity)
            {
                SetColor();
                colorDrity = false;
            }

            if (fillDrity || spriteDirty)
            {
                if (type == Image.Type.Filled)
                {
                    SetFillAmountRadial360(m_FillAmount, true);
                }
                else if (vertices.Length == 4)
                {
                    SetFillAmount(m_FillAmount);
                }

                fillDrity = false;
                spriteDirty = false;
            }

            if (positionDrity)
            {
                RefreshPostion();
                deltaPostion = Vector3.zero;
                positionDrity = false;
            }

            return true;
        }

        public override void OnPopulateMesh(VertexHelperEx toFill)
        {
        }

        void GenerateSprite()
        {
            if (vertices == null)
                return;

            if (type == Image.Type.Filled)
            {
                SetFillAmountRadial360(m_FillAmount, true);
            }
            else if (type == Image.Type.Sliced)
            {
                GenerateSlicedSprite();
            }
            else
            {
                if (mirror && vertices.Length == 6)
                    GenerateSimpleSpriteMirror();
                else
                    GenerateSimpleSprite();
            }
        }

        void GenerateSize()
        {
            if (mirror)
            {
                if (type == Image.Type.Sliced)
                {
                    GenerateSlicedSizeMirror();
                }
                else
                {
                    GenerateSimpleSizeMirror();
                }
            }
            else if (type == Image.Type.Sliced)
            {
                GenerateSlicedSize();
            }
            else if (vertices.Length == 4)
            {
                GenerateSimpleSize();
            }
        }

        public bool mirror = false;
        public MirrorType mirrorType = MirrorType.Horizontal;

        public void SetVertex(Mesh mesh, Transform root)
        {
            if (vertices == null || vertices.Length != mesh.vertexCount)
            {
                vertices = new VertexData[mesh.vertexCount];
            }

            if (mirror)
            {
                for (int i = 0; i < vertices.Length; i++)
                {
                    vertices[i].position =
                        root.transform.InverseTransformPoint(transform.TransformPoint(mesh.vertices[i]));
                    vertices[i].uv = new Vector4(mesh.uv[i].x, mesh.uv[i].y, mesh.uv2[i].x, mesh.uv2[i].y);
                    vertices[i].color = mesh.colors32[i];
                }
            }
            else
            {
                for (int i = 0; i < vertices.Length; i++)
                {
                    vertices[i].position =
                        root.transform.InverseTransformPoint(transform.TransformPoint(mesh.vertices[i]));
                    vertices[i].uv = new Vector4(mesh.uv[i].x, mesh.uv[i].y, mesh.uv2[i].x, mesh.uv2[i].y);
                    vertices[i].color = mesh.colors32[i];
                }
            }
        }

        public void SetSliceLTRB()
        {
            if (vertices == null)
                return;

            if (vertices.Length >= 36)
            {
                ltrb.x = vertices[2].position.x - vertices[0].position.x; //L
                ltrb.y = vertices[2].position.y - vertices[0].position.y; //T
                ltrb.z = vertices[35].position.x - vertices[33].position.x; //R
                ltrb.w = vertices[35].position.y - vertices[33].position.y; //B
            }
            //else
            //{
            //    Log.Error("SetSliceLTRB error");
            //}
        }

        private void GenerateSimpleSprite()
        {
            var uv = DataUtility.GetOuterUV(m_Sprite);

            int quadCount = vertices.Length / 4;

            for (int i = 0; i < quadCount; i++)
            {
                int n = i * 4;

                SetUv(uv.x, uv.y, n);
                SetUv(uv.x, uv.w, n + 1);
                SetUv(uv.z, uv.w, n + 2);
                SetUv(uv.z, uv.y, n + 3);
            }

            SetCanvasFlagDirty(MeshCanvasDirtyFlag.kUv);
        }

        private void GenerateSimpleSpriteMirror()
        {
            var uv = DataUtility.GetOuterUV(m_Sprite);

            int quadCount = vertices.Length / 6;

            for (int i = 0; i < quadCount; i++)
            {
                int n = i * 6;

                SetUv(uv.x, uv.y, n);
                SetUv(uv.x, uv.w, n + 1);
                SetUv(uv.z, uv.w, n + 2);
                SetUv(uv.z, uv.y, n + 3);

                SetUv(uv.x, uv.y, n + 4);
                SetUv(uv.x, uv.w, n + 5);
            }

            SetCanvasFlagDirty(MeshCanvasDirtyFlag.kUv);
        }

        void SetUv(float x, float y, int index)
        {
            vertices[index].uv.x = x;
            vertices[index].uv.y = y;
        }

        void UploadUv(float x, float y, int index)
        {
            SetUv(x, y, index);

            SetCanvasFlagDirty(MeshCanvasDirtyFlag.kUv);
        }

        void UploadUv(float x, float y, float x2, float y2, int index)
        {
            vertices[index].uv.x = x;
            vertices[index].uv.y = y;
            vertices[index].uv.z = x2;
            vertices[index].uv.w = y2;

            SetCanvasFlagDirty(MeshCanvasDirtyFlag.kUv);
        }

        void UploadUv(Vector4 uv, int index)
        {
            vertices[index].uv = uv;

            SetCanvasFlagDirty(MeshCanvasDirtyFlag.kUv);
        }

        private void SetVertexSize(int index, Vector2 delta)
        {
            vertices[index].position.x += delta.x;
            vertices[index].position.y += delta.y;

            if (isVisible == false)
            {
                return;
            }

            SetCanvasFlagDirty(MeshCanvasDirtyFlag.kPosition);
        }

        private void SetVertexSize(int index, float x, float y)
        {
            vertices[index].position.x = x;
            vertices[index].position.y = y;

            if (isVisible == false)
            {
                return;
            }

            SetCanvasFlagDirty(MeshCanvasDirtyFlag.kPosition);
        }

        private void GenerateSimpleSize()
        {
            int quadCount = vertices.Length / 4;
            int n = 0;
            Vector2 tmp = deltaSize;
            for (int i = 0; i < quadCount; i++)
            {
                tmp.x = -tmp.x;
                tmp.y = -tmp.y;
                SetVertexSize(n++, tmp);
                tmp.y = -tmp.y;
                SetVertexSize(n++, tmp);
                tmp.x = -tmp.x;
                SetVertexSize(n++, tmp);
                tmp.y = -tmp.y;
                SetVertexSize(n++, tmp);
            }
        }

        private void GenerateSimpleSizeMirror()
        {
            if (mirrorType == MirrorType.Horizontal)
            {
                Vector2 tmp = deltaSize;
                tmp.x = -tmp.x;
                tmp.y = -tmp.y;
                SetVertexSize(0, tmp);
                SetVertexSize(3, new Vector2(0, tmp.y));

                tmp.y = -tmp.y;
                SetVertexSize(1, tmp);
                SetVertexSize(2, new Vector2(0, tmp.y));

                tmp.x = -tmp.x;
                SetVertexSize(4, tmp);

                tmp.y = -tmp.y;
                SetVertexSize(5, tmp);
            }
            else if (mirrorType == MirrorType.Vertical)
            {
                Vector2 tmp = deltaSize;
                tmp.x = -tmp.x;
                tmp.y = -tmp.y;
                SetVertexSize(0, tmp);
                SetVertexSize(1, new Vector2(tmp.x, 0));

                tmp.y = -tmp.y;
                SetVertexSize(4, tmp);

                tmp.x = -tmp.x;
                SetVertexSize(5, tmp);

                tmp.y = -tmp.y;
                SetVertexSize(3, tmp);
                SetVertexSize(2, new Vector2(tmp.x, 0));
            }
        }

        float[] xValue = new float[4];
        float[] yValue = new float[4];

        private void GenerateSlicedSize()
        {
            if (!hasBorder)
            {
                GenerateSimpleSize();
                return;
            }

            if (vertices.Length >= 36)
            {
                float xscale = size.x / (ltrb.x + ltrb.z);
                float yscale = size.y / (ltrb.y + ltrb.w);
                if (xscale >= 1f)
                {
                    xscale = 1f;
                }

                if (yscale >= 1f)
                {
                    yscale = 1f;
                }

                xValue[0] = rect.x;
                xValue[1] = rect.x + ltrb.x * xscale;
                xValue[3] = rect.z;
                xValue[2] = rect.z - ltrb.z * xscale;
                yValue[0] = rect.y;
                yValue[1] = rect.y + ltrb.w * yscale;
                yValue[3] = rect.w;
                yValue[2] = rect.w - ltrb.y * yscale;
                for (int x = 0; x < 3; x++)
                {
                    for (int y = 0; y < 3; y++)
                    {
                        int m = x * 12 + y * 4;
                        SetVertexSize(m, xValue[x], yValue[y]);
                        SetVertexSize(m + 1, xValue[x], yValue[y + 1]);
                        SetVertexSize(m + 2, xValue[x + 1], yValue[y + 1]);
                        SetVertexSize(m + 3, xValue[x + 1], yValue[y]);
                    }
                }

                if (positionDrity)
                {
                    //上述计算方式下，不需要叠加deltaPosition，防止额外叠加导致错误
                    positionDrity = false;
                    deltaPostion = Vector3.zero;
                }

                return;
            }

            int n = 0;
            for (int x = 0; x < 3; ++x)
            {
                for (int y = 0; y < 3; ++y)
                {
                    if (n + 3 >= vertices.Length)
                        break;

                    var tmp = deltaSize;

                    if (x == 2)
                    {
                        tmp.x = -tmp.x;
                    }

                    if (y == 2)
                    {
                        tmp.y = -tmp.y;
                    }

                    if (x == 0 || x == 2)
                    {
                        if (y == 0 || y == 2)
                        {
                            SetVertexSize(n++, -tmp);
                            SetVertexSize(n++, -tmp);
                            SetVertexSize(n++, -tmp);
                            SetVertexSize(n++, -tmp);
                        }
                        else if (y == 1)
                        {
                            tmp.x = -tmp.x;
                            tmp.y = -tmp.y;
                            SetVertexSize(n++, tmp);
                            tmp.y = -tmp.y;
                            SetVertexSize(n++, tmp);
                            SetVertexSize(n++, tmp);
                            tmp.y = -tmp.y;
                            SetVertexSize(n++, tmp);
                        }
                    }
                    else if (x == 1)
                    {
                        if (y == 0 || y == 2)
                        {
                            tmp.x = -tmp.x;
                            tmp.y = -tmp.y;
                            SetVertexSize(n++, tmp);
                            SetVertexSize(n++, tmp);
                            tmp.x = -tmp.x;
                            SetVertexSize(n++, tmp);
                            SetVertexSize(n++, tmp);
                        }
                        else if (y == 1)
                        {
                            tmp.x = -tmp.x;
                            tmp.y = -tmp.y;
                            SetVertexSize(n++, tmp);
                            tmp.y = -tmp.y;
                            SetVertexSize(n++, tmp);
                            tmp.x = -tmp.x;
                            SetVertexSize(n++, tmp);
                            tmp.y = -tmp.y;
                            SetVertexSize(n++, tmp);
                        }
                    }
                }
            }
        }

        private void GenerateSlicedSizeMirror()
        {
            Vector4 border = Vector4.zero;
            if (activeSprite != null)
            {
                border = activeSprite.border;
            }

            if (vertices.Length == 72)
            {
                if (mirrorType == MirrorType.Horizontal)
                {
                    float xscale = (border.x + border.z) > 0f ? 0.5f * size.x / (border.x + border.z) : 0;
                    float yscale = (border.y + border.w) > 0f ? size.y / (border.y + border.w) : 0;
                    if (xscale >= 1f)
                    {
                        xscale = 1f;
                    }

                    if (yscale >= 1f)
                    {
                        yscale = 1f;
                    }

                    xValue[0] = rect.x;
                    xValue[1] = rect.x + border.x * xscale;
                    xValue[3] = (rect.z + rect.x) * 0.5f;
                    xValue[2] = (rect.z + rect.x) * 0.5f - border.z * xscale;
                    yValue[0] = rect.y;
                    yValue[1] = rect.y + border.y * yscale;
                    yValue[3] = rect.w;
                    yValue[2] = rect.w - border.w * yscale;
                    for (int x = 0; x < 3; x++)
                    {
                        for (int y = 0; y < 3; y++)
                        {
                            int m = x * 12 + y * 4;
                            SetVertexSize(m, xValue[x], yValue[y]);
                            SetVertexSize(m + 1, xValue[x], yValue[y + 1]);
                            SetVertexSize(m + 2, xValue[x + 1], yValue[y + 1]);
                            SetVertexSize(m + 3, xValue[x + 1], yValue[y]);
                        }
                    }

                    for (int i = 0; i < 36; i++)
                    {
                        Vector3 pos = vertices[i].position;
                        SetVertexSize(36 + i, (rect.z + rect.x) - pos.x, pos.y);
                    }
                }
                else if (mirrorType == MirrorType.Vertical)
                {
                    float xscale = (border.x + border.z) > 0f ? size.x / (border.x + border.z) : 0;
                    float yscale = (border.y + border.w) > 0f ? 0.5f * size.y / (border.y + border.w) : 0;
                    if (xscale >= 1f)
                    {
                        xscale = 1f;
                    }

                    if (yscale >= 1f)
                    {
                        yscale = 1f;
                    }

                    xValue[0] = rect.x;
                    xValue[1] = rect.x + border.x * xscale;
                    xValue[3] = rect.z;
                    xValue[2] = rect.z - border.z * xscale;
                    yValue[0] = rect.y;
                    yValue[1] = rect.y + border.y * yscale;
                    yValue[3] = (rect.w + rect.y) * 0.5f;
                    yValue[2] = (rect.w + rect.y) * 0.5f - border.w * yscale;
                    for (int x = 0; x < 3; x++)
                    {
                        for (int y = 0; y < 3; y++)
                        {
                            int m = x * 12 + y * 4;
                            SetVertexSize(m, xValue[x], yValue[y]);
                            SetVertexSize(m + 1, xValue[x], yValue[y + 1]);
                            SetVertexSize(m + 2, xValue[x + 1], yValue[y + 1]);
                            SetVertexSize(m + 3, xValue[x + 1], yValue[y]);
                        }
                    }

                    for (int i = 0; i < 36; i++)
                    {
                        Vector3 pos = vertices[i].position;
                        SetVertexSize(36 + i, pos.x, (rect.w + rect.y) - pos.y);
                    }
                }

                if (positionDrity)
                {
                    //上述计算方式下，不需要叠加deltaPosition，防止额外叠加导致错误
                    positionDrity = false;
                    deltaPostion = Vector3.zero;
                }

                return;
            }
        }

        private void GenerateSlicedSprite(bool refreshPos = false)
        {
            if (!hasBorder)
            {
                GenerateSimpleSprite();
                return;
            }

            Vector4 outer, inner;

            if (activeSprite != null)
            {
                outer = DataUtility.GetOuterUV(activeSprite);
                inner = DataUtility.GetInnerUV(activeSprite);
            }
            else
            {
                outer = Vector4.zero;
                inner = Vector4.zero;
            }

            s_Uv[0] = outer;
            s_Uv[1] = inner;
            s_Uv[2].x = inner.z;
            s_Uv[2].y = inner.w;
            s_Uv[3].x = outer.z;
            s_Uv[3].y = outer.w;

            int quadCount = 0;
            for (int x = 0; x < 3; ++x)
            {
                int x2 = x + 1;

                for (int y = 0; y < 3; ++y)
                {
                    int y2 = y + 1;
                    int n = quadCount * 4;

                    if (n + 3 >= vertices.Length)
                        break;

                    SetUv(s_Uv[x].x, s_Uv[y].y, n);
                    SetUv(s_Uv[x].x, s_Uv[y2].y, n + 1);
                    SetUv(s_Uv[x2].x, s_Uv[y2].y, n + 2);
                    SetUv(s_Uv[x2].x, s_Uv[y].y, n + 3);

                    quadCount += 1;
                }
            }

            if (mirror && vertices.Length == 72)
            {
                quadCount = 0;
                for (int x = 0; x < 3; ++x)
                {
                    int x2 = x + 1;

                    for (int y = 0; y < 3; ++y)
                    {
                        int y2 = y + 1;
                        int n = quadCount * 4;

                        if (n + 3 + 36 >= vertices.Length)
                            break;

                        SetUv(s_Uv[x].x, s_Uv[y].y, n + 36);
                        SetUv(s_Uv[x].x, s_Uv[y2].y, n + 1 + 36);
                        SetUv(s_Uv[x2].x, s_Uv[y2].y, n + 2 + 36);
                        SetUv(s_Uv[x2].x, s_Uv[y].y, n + 3 + 36);

                        quadCount += 1;
                    }
                }
            }

            SetCanvasFlagDirty(MeshCanvasDirtyFlag.kUv);
        }

        static bool RadialCut(Vector2[] xy, Vector4[] uv, float fill, bool invert, int corner)
        {
            if (fill < 0.001f) return false;

            if ((corner & 1) == 1) invert = !invert;

            if (!invert && fill > 0.999f) return true;

            float angle = Mathf.Clamp01(fill);
            if (invert) angle = 1f - angle;
            angle *= 90f * Mathf.Deg2Rad;

            float cos = Mathf.Cos(angle);
            float sin = Mathf.Sin(angle);

            RadialCut(xy, cos, sin, invert, corner);
            RadialCut(uv, cos, sin, invert, corner);
            return true;
        }

        static void RadialCut(Vector2[] xy, float cos, float sin, bool invert, int corner)
        {
            int i0 = corner;
            int i1 = ((corner + 1) % 4);
            int i2 = ((corner + 2) % 4);
            int i3 = ((corner + 3) % 4);

            if ((corner & 1) == 1)
            {
                if (sin > cos)
                {
                    cos /= sin;
                    sin = 1f;

                    if (invert)
                    {
                        xy[i1].x = Mathf.Lerp(xy[i0].x, xy[i2].x, cos);
                        xy[i2].x = xy[i1].x;
                    }
                }
                else if (cos > sin)
                {
                    sin /= cos;
                    cos = 1f;

                    if (!invert)
                    {
                        xy[i2].y = Mathf.Lerp(xy[i0].y, xy[i2].y, sin);
                        xy[i3].y = xy[i2].y;
                    }
                }
                else
                {
                    cos = 1f;
                    sin = 1f;
                }

                if (!invert) xy[i3].x = Mathf.Lerp(xy[i0].x, xy[i2].x, cos);
                else xy[i1].y = Mathf.Lerp(xy[i0].y, xy[i2].y, sin);
            }
            else
            {
                if (cos > sin)
                {
                    sin /= cos;
                    cos = 1f;

                    if (!invert)
                    {
                        xy[i1].y = Mathf.Lerp(xy[i0].y, xy[i2].y, sin);
                        xy[i2].y = xy[i1].y;
                    }
                }
                else if (sin > cos)
                {
                    cos /= sin;
                    sin = 1f;

                    if (invert)
                    {
                        xy[i2].x = Mathf.Lerp(xy[i0].x, xy[i2].x, cos);
                        xy[i3].x = xy[i2].x;
                    }
                }
                else
                {
                    cos = 1f;
                    sin = 1f;
                }

                if (invert) xy[i3].y = Mathf.Lerp(xy[i0].y, xy[i2].y, sin);
                else xy[i1].x = Mathf.Lerp(xy[i0].x, xy[i2].x, cos);
            }
        }

        static void RadialCut(Vector4[] xyzw, float cos, float sin, bool invert, int corner)
        {
            int i0 = corner;
            int i1 = ((corner + 1) % 4);
            int i2 = ((corner + 2) % 4);
            int i3 = ((corner + 3) % 4);

            if ((corner & 1) == 1)
            {
                if (sin > cos)
                {
                    cos /= sin;
                    sin = 1f;

                    if (invert)
                    {
                        xyzw[i1].x = Mathf.Lerp(xyzw[i0].x, xyzw[i2].x, cos);
                        xyzw[i2].x = xyzw[i1].x;

                        xyzw[i1].z = Mathf.Lerp(xyzw[i0].z, xyzw[i2].z, cos);
                        xyzw[i2].z = xyzw[i1].z;
                    }
                }
                else if (cos > sin)
                {
                    sin /= cos;
                    cos = 1f;

                    if (!invert)
                    {
                        xyzw[i2].y = Mathf.Lerp(xyzw[i0].y, xyzw[i2].y, sin);
                        xyzw[i3].y = xyzw[i2].y;

                        xyzw[i2].w = Mathf.Lerp(xyzw[i0].w, xyzw[i2].w, sin);
                        xyzw[i3].w = xyzw[i2].w;
                    }
                }
                else
                {
                    cos = 1f;
                    sin = 1f;
                }

                if (!invert)
                {
                    xyzw[i3].x = Mathf.Lerp(xyzw[i0].x, xyzw[i2].x, cos);
                    xyzw[i3].z = Mathf.Lerp(xyzw[i0].z, xyzw[i2].z, cos);
                }
                else
                {
                    xyzw[i1].y = Mathf.Lerp(xyzw[i0].y, xyzw[i2].y, sin);
                    xyzw[i1].w = Mathf.Lerp(xyzw[i0].w, xyzw[i2].w, sin);
                }
            }
            else
            {
                if (cos > sin)
                {
                    sin /= cos;
                    cos = 1f;

                    if (!invert)
                    {
                        xyzw[i1].y = Mathf.Lerp(xyzw[i0].y, xyzw[i2].y, sin);
                        xyzw[i2].y = xyzw[i1].y;

                        xyzw[i1].w = Mathf.Lerp(xyzw[i0].w, xyzw[i2].w, sin);
                        xyzw[i2].w = xyzw[i1].w;
                    }
                }
                else if (sin > cos)
                {
                    cos /= sin;
                    sin = 1f;

                    if (invert)
                    {
                        xyzw[i2].x = Mathf.Lerp(xyzw[i0].x, xyzw[i2].x, cos);
                        xyzw[i3].x = xyzw[i2].x;

                        xyzw[i2].z = Mathf.Lerp(xyzw[i0].z, xyzw[i2].z, cos);
                        xyzw[i3].z = xyzw[i2].z;
                    }
                }
                else
                {
                    cos = 1f;
                    sin = 1f;
                }

                if (invert)
                {
                    xyzw[i3].y = Mathf.Lerp(xyzw[i0].y, xyzw[i2].y, sin);
                    xyzw[i3].w = Mathf.Lerp(xyzw[i0].w, xyzw[i2].w, sin);
                }
                else
                {
                    xyzw[i1].x = Mathf.Lerp(xyzw[i0].x, xyzw[i2].x, cos);
                    xyzw[i1].z = Mathf.Lerp(xyzw[i0].z, xyzw[i2].z, cos);
                }
            }
        }


        private void Awake()
        {
            //后期可以去掉，现在是为了兼容旧的没有保存LTRB信息的mesh
            if (type == Image.Type.Sliced && ltrb == Vector4.zero)
            {
                SetSliceLTRB();
            }
        }
    }
}